Coverage Summary for Class: AbstractBaseGraph (com.google.common.graph)
| Class | Method, % | Line, % |
|---|---|---|
| AbstractBaseGraph | 0% (0/12) | 0% (0/31) |
| AbstractBaseGraph$1 | 0% (0/5) | 0% (0/10) |
| AbstractBaseGraph$2 | 0% (0/2) | 0% (0/11) |
| AbstractBaseGraph$2$1 | 0% (0/2) | 0% (0/2) |
| AbstractBaseGraph$2$2 | 0% (0/2) | 0% (0/2) |
| AbstractBaseGraph$2$3 | 0% (0/2) | 0% (0/2) |
| Total | 0% (0/25) | 0% (0/58) |
1 /* 2 * Copyright (C) 2017 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.graph; 18 19 import static com.google.common.base.Preconditions.checkArgument; 20 import static com.google.common.base.Preconditions.checkNotNull; 21 import static com.google.common.base.Preconditions.checkState; 22 import static com.google.common.graph.GraphConstants.ENDPOINTS_MISMATCH; 23 24 import com.google.common.base.Function; 25 import com.google.common.collect.ImmutableSet; 26 import com.google.common.collect.Iterators; 27 import com.google.common.collect.Sets; 28 import com.google.common.collect.UnmodifiableIterator; 29 import com.google.common.math.IntMath; 30 import com.google.common.primitives.Ints; 31 import java.util.AbstractSet; 32 import java.util.Set; 33 import javax.annotation.CheckForNull; 34 35 /** 36 * This class provides a skeletal implementation of {@link BaseGraph}. 37 * 38 * <p>The methods implemented in this class should not be overridden unless the subclass admits a 39 * more efficient implementation. 40 * 41 * @author James Sexton 42 * @param <N> Node parameter type 43 */ 44 @ElementTypesAreNonnullByDefault 45 abstract class AbstractBaseGraph<N> implements BaseGraph<N> { 46 47 /** 48 * Returns the number of edges in this graph; used to calculate the size of {@link #edges()}. This 49 * implementation requires O(|N|) time. Classes extending this one may manually keep track of the 50 * number of edges as the graph is updated, and override this method for better performance. 51 */ 52 protected long edgeCount() { 53 long degreeSum = 0L; 54 for (N node : nodes()) { 55 degreeSum += degree(node); 56 } 57 // According to the degree sum formula, this is equal to twice the number of edges. 58 checkState((degreeSum & 1) == 0); 59 return degreeSum >>> 1; 60 } 61 62 /** 63 * An implementation of {@link BaseGraph#edges()} defined in terms of {@link #nodes()} and {@link 64 * #successors(Object)}. 65 */ 66 @Override 67 public Set<EndpointPair<N>> edges() { 68 return new AbstractSet<EndpointPair<N>>() { 69 @Override 70 public UnmodifiableIterator<EndpointPair<N>> iterator() { 71 return EndpointPairIterator.of(AbstractBaseGraph.this); 72 } 73 74 @Override 75 public int size() { 76 return Ints.saturatedCast(edgeCount()); 77 } 78 79 @Override 80 public boolean remove(@CheckForNull Object o) { 81 throw new UnsupportedOperationException(); 82 } 83 84 // Mostly safe: We check contains(u) before calling successors(u), so we perform unsafe 85 // operations only in weird cases like checking for an EndpointPair<ArrayList> in a 86 // Graph<LinkedList>. 87 @SuppressWarnings("unchecked") 88 @Override 89 public boolean contains(@CheckForNull Object obj) { 90 if (!(obj instanceof EndpointPair)) { 91 return false; 92 } 93 EndpointPair<?> endpointPair = (EndpointPair<?>) obj; 94 return isOrderingCompatible(endpointPair) 95 && nodes().contains(endpointPair.nodeU()) 96 && successors((N) endpointPair.nodeU()).contains(endpointPair.nodeV()); 97 } 98 }; 99 } 100 101 @Override 102 public ElementOrder<N> incidentEdgeOrder() { 103 return ElementOrder.unordered(); 104 } 105 106 @Override 107 public Set<EndpointPair<N>> incidentEdges(N node) { 108 checkNotNull(node); 109 checkArgument(nodes().contains(node), "Node %s is not an element of this graph.", node); 110 return new IncidentEdgeSet<N>(this, node) { 111 @Override 112 public UnmodifiableIterator<EndpointPair<N>> iterator() { 113 if (graph.isDirected()) { 114 return Iterators.unmodifiableIterator( 115 Iterators.concat( 116 Iterators.transform( 117 graph.predecessors(node).iterator(), 118 new Function<N, EndpointPair<N>>() { 119 @Override 120 public EndpointPair<N> apply(N predecessor) { 121 return EndpointPair.ordered(predecessor, node); 122 } 123 }), 124 Iterators.transform( 125 // filter out 'node' from successors (already covered by predecessors, above) 126 Sets.difference(graph.successors(node), ImmutableSet.of(node)).iterator(), 127 new Function<N, EndpointPair<N>>() { 128 @Override 129 public EndpointPair<N> apply(N successor) { 130 return EndpointPair.ordered(node, successor); 131 } 132 }))); 133 } else { 134 return Iterators.unmodifiableIterator( 135 Iterators.transform( 136 graph.adjacentNodes(node).iterator(), 137 new Function<N, EndpointPair<N>>() { 138 @Override 139 public EndpointPair<N> apply(N adjacentNode) { 140 return EndpointPair.unordered(node, adjacentNode); 141 } 142 })); 143 } 144 } 145 }; 146 } 147 148 @Override 149 public int degree(N node) { 150 if (isDirected()) { 151 return IntMath.saturatedAdd(predecessors(node).size(), successors(node).size()); 152 } else { 153 Set<N> neighbors = adjacentNodes(node); 154 int selfLoopCount = (allowsSelfLoops() && neighbors.contains(node)) ? 1 : 0; 155 return IntMath.saturatedAdd(neighbors.size(), selfLoopCount); 156 } 157 } 158 159 @Override 160 public int inDegree(N node) { 161 return isDirected() ? predecessors(node).size() : degree(node); 162 } 163 164 @Override 165 public int outDegree(N node) { 166 return isDirected() ? successors(node).size() : degree(node); 167 } 168 169 @Override 170 public boolean hasEdgeConnecting(N nodeU, N nodeV) { 171 checkNotNull(nodeU); 172 checkNotNull(nodeV); 173 return nodes().contains(nodeU) && successors(nodeU).contains(nodeV); 174 } 175 176 @Override 177 public boolean hasEdgeConnecting(EndpointPair<N> endpoints) { 178 checkNotNull(endpoints); 179 if (!isOrderingCompatible(endpoints)) { 180 return false; 181 } 182 N nodeU = endpoints.nodeU(); 183 N nodeV = endpoints.nodeV(); 184 return nodes().contains(nodeU) && successors(nodeU).contains(nodeV); 185 } 186 187 /** 188 * Throws {@code IllegalArgumentException} if the ordering of {@code endpoints} is not compatible 189 * with the directionality of this graph. 190 */ 191 protected final void validateEndpoints(EndpointPair<?> endpoints) { 192 checkNotNull(endpoints); 193 checkArgument(isOrderingCompatible(endpoints), ENDPOINTS_MISMATCH); 194 } 195 196 protected final boolean isOrderingCompatible(EndpointPair<?> endpoints) { 197 return endpoints.isOrdered() || !this.isDirected(); 198 } 199 }