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

com.google.javascript.jscomp.graph.LinkedDirectedGraph Maven / Gradle / Ivy

Go to download

Closure Compiler is a JavaScript optimizing compiler. It parses your JavaScript, analyzes it, removes dead code and rewrites and minimizes what's left. It also checks syntax, variable references, and types, and warns about common JavaScript pitfalls. It is used in many of Google's JavaScript apps, including Gmail, Google Web Search, Google Maps, and Google Docs.

There is a newer version: v20240317
Show newest version
/*
 * Copyright 2008 The Closure Compiler Authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.javascript.jscomp.graph;

import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * A directed graph using linked list within nodes to store edge information.
 * 

* This implementation favors directed graph operations inherited from * DirectedGraph. * Operations from Graph would tends to be slower. * * * @param Value type that the graph node stores. * @param Value type that the graph edge stores. */ public class LinkedDirectedGraph extends DiGraph implements GraphvizGraph { protected final Map> nodes = Maps.newHashMap(); public SubGraph newSubGraph() { return new SimpleSubGraph(this); } public static LinkedDirectedGraph createWithoutAnnotations() { return new LinkedDirectedGraph(false, false); } public static LinkedDirectedGraph createWithNodeAnnotations() { return new LinkedDirectedGraph(true, false); } public static LinkedDirectedGraph createWithEdgeAnnotations() { return new LinkedDirectedGraph(false, true); } public static LinkedDirectedGraph create() { return new LinkedDirectedGraph(true, true); } private final boolean useNodeAnnotations; private final boolean useEdgeAnnotations; protected LinkedDirectedGraph( boolean useNodeAnnotations, boolean useEdgeAnnotations) { this.useNodeAnnotations = useNodeAnnotations; this.useEdgeAnnotations = useEdgeAnnotations; } @Override public void connect(N srcValue, E edgeValue, N destValue) { LinkedDirectedGraphNode src = getNodeOrFail(srcValue); LinkedDirectedGraphNode dest = getNodeOrFail(destValue); LinkedDirectedGraphEdge edge = useEdgeAnnotations ? new AnnotatedLinkedDirectedGraphEdge(src, edgeValue, dest) : new LinkedDirectedGraphEdge(src, edgeValue, dest); src.getOutEdges().add(edge); dest.getInEdges().add(edge); } @Override public void disconnect(N n1, N n2) { disconnectInDirection(n1, n2); disconnectInDirection(n2, n1); } @Override public void disconnectInDirection(N srcValue, N destValue) { LinkedDirectedGraphNode src = getNodeOrFail(srcValue); LinkedDirectedGraphNode dest = getNodeOrFail(destValue); for (DiGraphEdge edge : getDirectedGraphEdges(srcValue, destValue)) { src.getOutEdges().remove(edge); dest.getInEdges().remove(edge); } } @Override public Iterable> getDirectedGraphNodes() { return Collections.>unmodifiableCollection( nodes.values()); } @Override public DiGraphNode getDirectedGraphNode(N nodeValue) { return nodes.get(nodeValue); } @Override public GraphNode getNode(N nodeValue) { return getDirectedGraphNode(nodeValue); } @Override public List> getInEdges(N nodeValue) { LinkedDirectedGraphNode node = getNodeOrFail(nodeValue); return Collections.>unmodifiableList(node.getInEdges()); } @Override public List> getOutEdges(N nodeValue) { LinkedDirectedGraphNode node = getNodeOrFail(nodeValue); return Collections.>unmodifiableList(node.getOutEdges()); } @Override public DiGraphNode createDirectedGraphNode(N nodeValue) { LinkedDirectedGraphNode node = nodes.get(nodeValue); if (node == null) { node = useNodeAnnotations ? new AnnotatedLinkedDirectedGraphNode(nodeValue) : new LinkedDirectedGraphNode(nodeValue); nodes.put(nodeValue, node); } return node; } @Override public List> getEdges(N n1, N n2) { // Since this is a method from a generic graph, edges from both // directions must be added to the returning list. List> forwardEdges = getDirectedGraphEdges(n1, n2); List> backwardEdges = getDirectedGraphEdges(n2, n1); int totalSize = forwardEdges.size() + backwardEdges.size(); List> edges = Lists.newArrayListWithCapacity(totalSize); edges.addAll(forwardEdges); edges.addAll(backwardEdges); return edges; } @Override public GraphNode createNode(N value) { return createDirectedGraphNode(value); } @Override public List> getDirectedGraphEdges(N n1, N n2) { DiGraphNode dNode1 = getNodeOrFail(n1); DiGraphNode dNode2 = getNodeOrFail(n2); List> edges = Lists.newArrayList(); for (DiGraphEdge outEdge : dNode1.getOutEdges()) { if (outEdge.getDestination() == dNode2) { edges.add(outEdge); } } return edges; } @Override public boolean isConnectedInDirection(N n1, N n2) { return isConnectedInDirection(n1, Predicates.alwaysTrue(), n2); } @Override public boolean isConnectedInDirection(N n1, E edgeValue, N n2) { return isConnectedInDirection(n1, Predicates.equalTo(edgeValue), n2); } private boolean isConnectedInDirection(N n1, Predicate edgeMatcher, N n2) { // Verify the nodes. DiGraphNode dNode1 = getNodeOrFail(n1); DiGraphNode dNode2 = getNodeOrFail(n2); for (DiGraphEdge outEdge : dNode1.getOutEdges()) { if (outEdge.getDestination() == dNode2 && edgeMatcher.apply(outEdge.getValue())) { return true; } } return false; } @Override public List> getDirectedPredNodes(N nodeValue) { return getDirectedPredNodes(nodes.get(nodeValue)); } @Override public List> getDirectedSuccNodes(N nodeValue) { return getDirectedSuccNodes(nodes.get(nodeValue)); } @Override public List> getDirectedPredNodes( DiGraphNode dNode) { if (dNode == null) { throw new IllegalArgumentException(dNode + " is null"); } List> nodeList = Lists.newArrayList(); for (DiGraphEdge edge : dNode.getInEdges()) { nodeList.add(edge.getSource()); } return nodeList; } @Override public List> getDirectedSuccNodes( DiGraphNode dNode) { if (dNode == null) { throw new IllegalArgumentException(dNode + " is null"); } List> nodeList = Lists.newArrayList(); for (DiGraphEdge edge : dNode.getOutEdges()) { nodeList.add(edge.getDestination()); } return nodeList; } @Override public List getGraphvizEdges() { List edgeList = Lists.newArrayList(); for (LinkedDirectedGraphNode node : nodes.values()) { for (DiGraphEdge edge : node.getOutEdges()) { edgeList.add((LinkedDirectedGraphEdge) edge); } } return edgeList; } @Override public List getGraphvizNodes() { List nodeList = Lists.newArrayListWithCapacity(nodes.size()); for (LinkedDirectedGraphNode node : nodes.values()) { nodeList.add(node); } return nodeList; } @Override public String getName() { return "LinkedGraph"; } @Override public boolean isDirected() { return true; } @Override public Collection> getNodes() { return Collections.>unmodifiableCollection(nodes.values()); } @Override public List> getNeighborNodes(N value) { DiGraphNode node = getDirectedGraphNode(value); return getNeighborNodes(node); } public List> getNeighborNodes(DiGraphNode node) { List> result = Lists.newArrayList(); for (Iterator> i = ((LinkedDirectedGraphNode) node).neighborIterator();i.hasNext();) { result.add(i.next()); } return result; } @Override public Iterator> getNeighborNodesIterator(N value) { LinkedDirectedGraphNode node = nodes.get(value); Preconditions.checkNotNull(node); return node.neighborIterator(); } @Override public List> getEdges() { List> result = Lists.newArrayList(); for (DiGraphNode node : nodes.values()) { for (DiGraphEdge edge : node.getOutEdges()) { result.add(edge); } } return Collections.unmodifiableList(result); } @Override public int getNodeDegree(N value) { DiGraphNode node = getNodeOrFail(value); return node.getInEdges().size() + node.getOutEdges().size(); } /** * A directed graph node that stores outgoing edges and incoming edges as an * list within the node itself. */ static class LinkedDirectedGraphNode implements DiGraphNode, GraphvizNode { List> inEdgeList = Lists.newArrayList(); List> outEdgeList = Lists.newArrayList(); protected final N value; /** * Constructor * * @param nodeValue Node's value. */ LinkedDirectedGraphNode(N nodeValue) { this.value = nodeValue; } @Override public N getValue() { return value; } @Override public A getAnnotation() { throw new UnsupportedOperationException( "Graph initialized with node annotations turned off"); } @Override public void setAnnotation(Annotation data) { throw new UnsupportedOperationException( "Graph initialized with node annotations turned off"); } @Override public String getColor() { return "white"; } @Override public String getId() { return "LDN" + hashCode(); } @Override public String getLabel() { return value != null ? value.toString() : "null"; } @Override public String toString() { return getLabel(); } @Override public List> getInEdges() { return inEdgeList; } @Override public List> getOutEdges() { return outEdgeList; } private Iterator> neighborIterator() { return new NeighborIterator(); } private class NeighborIterator implements Iterator> { private final Iterator> in = inEdgeList.iterator(); private final Iterator> out = outEdgeList.iterator(); @Override public boolean hasNext() { return in.hasNext() || out.hasNext(); } @Override public GraphNode next() { boolean isOut = !in.hasNext(); Iterator> curIterator = isOut ? out : in; DiGraphEdge s = curIterator.next(); return isOut ? s.getDestination() : s.getSource(); } @Override public void remove() { throw new UnsupportedOperationException("Remove not supported."); } } } /** * A directed graph node with annotations. */ static class AnnotatedLinkedDirectedGraphNode extends LinkedDirectedGraphNode { protected Annotation annotation; /** * @param nodeValue Node's value. */ AnnotatedLinkedDirectedGraphNode(N nodeValue) { super(nodeValue); } @SuppressWarnings("unchecked") @Override public A getAnnotation() { return (A) annotation; } @Override public void setAnnotation(Annotation data) { annotation = data; } } /** * A directed graph edge that stores the source and destination nodes at each * edge. */ static class LinkedDirectedGraphEdge implements DiGraphEdge, GraphvizEdge { private DiGraphNode sourceNode; private DiGraphNode destNode; protected final E value; /** * Constructor. * * @param edgeValue Edge Value. */ LinkedDirectedGraphEdge(DiGraphNode sourceNode, E edgeValue, DiGraphNode destNode) { this.value = edgeValue; this.sourceNode = sourceNode; this.destNode = destNode; } @Override public DiGraphNode getSource() { return sourceNode; } @Override public DiGraphNode getDestination() { return destNode; } @Override public void setDestination(DiGraphNode node) { destNode = node; } @Override public void setSource(DiGraphNode node) { sourceNode = node; } @Override public E getValue() { return value; } @Override public A getAnnotation() { throw new UnsupportedOperationException( "Graph initialized with edge annotations turned off"); } @Override public void setAnnotation(Annotation data) { throw new UnsupportedOperationException( "Graph initialized with edge annotations turned off"); } @Override public String getColor() { return "black"; } @Override public String getLabel() { return value != null ? value.toString() : "null"; } @Override public String getNode1Id() { return ((LinkedDirectedGraphNode) sourceNode).getId(); } @Override public String getNode2Id() { return ((LinkedDirectedGraphNode) destNode).getId(); } @Override public String toString() { return sourceNode.toString() + " -> " + destNode.toString(); } @Override public GraphNode getNodeA() { return sourceNode; } @Override public GraphNode getNodeB() { return destNode; } } /** * A directed graph edge that stores the source and destination nodes at each * edge. */ static class AnnotatedLinkedDirectedGraphEdge extends LinkedDirectedGraphEdge { protected Annotation annotation; /** * Constructor. * * @param edgeValue Edge Value. */ AnnotatedLinkedDirectedGraphEdge(DiGraphNode sourceNode, E edgeValue, DiGraphNode destNode) { super(sourceNode, edgeValue, destNode); } @SuppressWarnings("unchecked") @Override public A getAnnotation() { return (A) annotation; } @Override public void setAnnotation(Annotation data) { annotation = data; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy