Coverage Summary for Class: ImmutableNetwork (com.google.common.graph)

Class Method, % Line, %
ImmutableNetwork 0% (0/10) 0% (0/32)
ImmutableNetwork$1 0% (0/2) 0% (0/2)
ImmutableNetwork$2 0% (0/2) 0% (0/2)
ImmutableNetwork$3 0% (0/2) 0% (0/2)
ImmutableNetwork$Builder 0% (0/5) 0% (0/9)
Total 0% (0/21) 0% (0/47)


1 /* 2  * Copyright (C) 2014 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.checkNotNull; 20  21 import com.google.common.annotations.Beta; 22 import com.google.common.base.Function; 23 import com.google.common.collect.ImmutableMap; 24 import com.google.common.collect.Maps; 25 import com.google.errorprone.annotations.CanIgnoreReturnValue; 26 import com.google.errorprone.annotations.Immutable; 27 import java.util.Map; 28  29 /** 30  * A {@link Network} whose elements and structural relationships will never change. Instances of 31  * this class may be obtained with {@link #copyOf(Network)}. 32  * 33  * <p>See the Guava User's Guide's <a 34  * href="https://github.com/google/guava/wiki/GraphsExplained#immutable-implementations">discussion 35  * of the {@code Immutable*} types</a> for more information on the properties and guarantees 36  * provided by this class. 37  * 38  * @author James Sexton 39  * @author Joshua O'Madadhain 40  * @author Omar Darwish 41  * @author Jens Nyman 42  * @param <N> Node parameter type 43  * @param <E> Edge parameter type 44  * @since 20.0 45  */ 46 @Beta 47 @Immutable(containerOf = {"N", "E"}) 48 @SuppressWarnings("Immutable") // Extends StandardNetwork but uses ImmutableMaps. 49 @ElementTypesAreNonnullByDefault 50 public final class ImmutableNetwork<N, E> extends StandardNetwork<N, E> { 51  52  private ImmutableNetwork(Network<N, E> network) { 53  super( 54  NetworkBuilder.from(network), getNodeConnections(network), getEdgeToReferenceNode(network)); 55  } 56  57  /** Returns an immutable copy of {@code network}. */ 58  public static <N, E> ImmutableNetwork<N, E> copyOf(Network<N, E> network) { 59  return (network instanceof ImmutableNetwork) 60  ? (ImmutableNetwork<N, E>) network 61  : new ImmutableNetwork<N, E>(network); 62  } 63  64  /** 65  * Simply returns its argument. 66  * 67  * @deprecated no need to use this 68  */ 69  @Deprecated 70  public static <N, E> ImmutableNetwork<N, E> copyOf(ImmutableNetwork<N, E> network) { 71  return checkNotNull(network); 72  } 73  74  @Override 75  public ImmutableGraph<N> asGraph() { 76  return new ImmutableGraph<N>(super.asGraph()); // safe because the view is effectively immutable 77  } 78  79  private static <N, E> Map<N, NetworkConnections<N, E>> getNodeConnections(Network<N, E> network) { 80  // ImmutableMap.Builder maintains the order of the elements as inserted, so the map will have 81  // whatever ordering the network's nodes do, so ImmutableSortedMap is unnecessary even if the 82  // input nodes are sorted. 83  ImmutableMap.Builder<N, NetworkConnections<N, E>> nodeConnections = ImmutableMap.builder(); 84  for (N node : network.nodes()) { 85  nodeConnections.put(node, connectionsOf(network, node)); 86  } 87  return nodeConnections.build(); 88  } 89  90  private static <N, E> Map<E, N> getEdgeToReferenceNode(Network<N, E> network) { 91  // ImmutableMap.Builder maintains the order of the elements as inserted, so the map will have 92  // whatever ordering the network's edges do, so ImmutableSortedMap is unnecessary even if the 93  // input edges are sorted. 94  ImmutableMap.Builder<E, N> edgeToReferenceNode = ImmutableMap.builder(); 95  for (E edge : network.edges()) { 96  edgeToReferenceNode.put(edge, network.incidentNodes(edge).nodeU()); 97  } 98  return edgeToReferenceNode.build(); 99  } 100  101  private static <N, E> NetworkConnections<N, E> connectionsOf(Network<N, E> network, N node) { 102  if (network.isDirected()) { 103  Map<E, N> inEdgeMap = Maps.asMap(network.inEdges(node), sourceNodeFn(network)); 104  Map<E, N> outEdgeMap = Maps.asMap(network.outEdges(node), targetNodeFn(network)); 105  int selfLoopCount = network.edgesConnecting(node, node).size(); 106  return network.allowsParallelEdges() 107  ? DirectedMultiNetworkConnections.ofImmutable(inEdgeMap, outEdgeMap, selfLoopCount) 108  : DirectedNetworkConnections.ofImmutable(inEdgeMap, outEdgeMap, selfLoopCount); 109  } else { 110  Map<E, N> incidentEdgeMap = 111  Maps.asMap(network.incidentEdges(node), adjacentNodeFn(network, node)); 112  return network.allowsParallelEdges() 113  ? UndirectedMultiNetworkConnections.ofImmutable(incidentEdgeMap) 114  : UndirectedNetworkConnections.ofImmutable(incidentEdgeMap); 115  } 116  } 117  118  private static <N, E> Function<E, N> sourceNodeFn(final Network<N, E> network) { 119  return new Function<E, N>() { 120  @Override 121  public N apply(E edge) { 122  return network.incidentNodes(edge).source(); 123  } 124  }; 125  } 126  127  private static <N, E> Function<E, N> targetNodeFn(final Network<N, E> network) { 128  return new Function<E, N>() { 129  @Override 130  public N apply(E edge) { 131  return network.incidentNodes(edge).target(); 132  } 133  }; 134  } 135  136  private static <N, E> Function<E, N> adjacentNodeFn(final Network<N, E> network, final N node) { 137  return new Function<E, N>() { 138  @Override 139  public N apply(E edge) { 140  return network.incidentNodes(edge).adjacentNode(node); 141  } 142  }; 143  } 144  145  /** 146  * A builder for creating {@link ImmutableNetwork} instances, especially {@code static final} 147  * networks. Example: 148  * 149  * <pre>{@code 150  * static final ImmutableNetwork<City, Train> TRAIN_NETWORK = 151  * NetworkBuilder.undirected() 152  * .allowsParallelEdges(true) 153  * .<City, Train>immutable() 154  * .addEdge(PARIS, BRUSSELS, Thalys.trainNumber("1111")) 155  * .addEdge(PARIS, BRUSSELS, RegionalTrain.trainNumber("2222")) 156  * .addEdge(LONDON, PARIS, Eurostar.trainNumber("3333")) 157  * .addEdge(LONDON, BRUSSELS, Eurostar.trainNumber("4444")) 158  * .addNode(REYKJAVIK) 159  * .build(); 160  * }</pre> 161  * 162  * <p>Builder instances can be reused; it is safe to call {@link #build} multiple times to build 163  * multiple networks in series. Each new network contains all the elements of the ones created 164  * before it. 165  * 166  * @since 28.0 167  */ 168  public static class Builder<N, E> { 169  170  private final MutableNetwork<N, E> mutableNetwork; 171  172  Builder(NetworkBuilder<N, E> networkBuilder) { 173  this.mutableNetwork = networkBuilder.build(); 174  } 175  176  /** 177  * Adds {@code node} if it is not already present. 178  * 179  * <p><b>Nodes must be unique</b>, just as {@code Map} keys must be. They must also be non-null. 180  * 181  * @return this {@code Builder} object 182  */ 183  @CanIgnoreReturnValue 184  public ImmutableNetwork.Builder<N, E> addNode(N node) { 185  mutableNetwork.addNode(node); 186  return this; 187  } 188  189  /** 190  * Adds {@code edge} connecting {@code nodeU} to {@code nodeV}. 191  * 192  * <p>If the network is directed, {@code edge} will be directed in this network; otherwise, it 193  * will be undirected. 194  * 195  * <p><b>{@code edge} must be unique to this network</b>, just as a {@code Map} key must be. It 196  * must also be non-null. 197  * 198  * <p>If {@code nodeU} and {@code nodeV} are not already present in this network, this method 199  * will silently {@link #addNode(Object) add} {@code nodeU} and {@code nodeV} to the network. 200  * 201  * <p>If {@code edge} already connects {@code nodeU} to {@code nodeV} (in the specified order if 202  * this network {@link #isDirected()}, else in any order), then this method will have no effect. 203  * 204  * @return this {@code Builder} object 205  * @throws IllegalArgumentException if {@code edge} already exists in the network and does not 206  * connect {@code nodeU} to {@code nodeV} 207  * @throws IllegalArgumentException if the introduction of the edge would violate {@link 208  * #allowsParallelEdges()} or {@link #allowsSelfLoops()} 209  */ 210  @CanIgnoreReturnValue 211  public ImmutableNetwork.Builder<N, E> addEdge(N nodeU, N nodeV, E edge) { 212  mutableNetwork.addEdge(nodeU, nodeV, edge); 213  return this; 214  } 215  216  /** 217  * Adds {@code edge} connecting {@code endpoints}. In an undirected network, {@code edge} will 218  * also connect {@code nodeV} to {@code nodeU}. 219  * 220  * <p>If this network is directed, {@code edge} will be directed in this network; if it is 221  * undirected, {@code edge} will be undirected in this network. 222  * 223  * <p>If this network is directed, {@code endpoints} must be ordered. 224  * 225  * <p><b>{@code edge} must be unique to this network</b>, just as a {@code Map} key must be. It 226  * must also be non-null. 227  * 228  * <p>If either or both endpoints are not already present in this network, this method will 229  * silently {@link #addNode(Object) add} each missing endpoint to the network. 230  * 231  * <p>If {@code edge} already connects an endpoint pair equal to {@code endpoints}, then this 232  * method will have no effect. 233  * 234  * @return this {@code Builder} object 235  * @throws IllegalArgumentException if {@code edge} already exists in the network and connects 236  * some other endpoint pair that is not equal to {@code endpoints} 237  * @throws IllegalArgumentException if the introduction of the edge would violate {@link 238  * #allowsParallelEdges()} or {@link #allowsSelfLoops()} 239  * @throws IllegalArgumentException if the endpoints are unordered and the network is directed 240  */ 241  @CanIgnoreReturnValue 242  public ImmutableNetwork.Builder<N, E> addEdge(EndpointPair<N> endpoints, E edge) { 243  mutableNetwork.addEdge(endpoints, edge); 244  return this; 245  } 246  247  /** 248  * Returns a newly-created {@code ImmutableNetwork} based on the contents of this {@code 249  * Builder}. 250  */ 251  public ImmutableNetwork<N, E> build() { 252  return ImmutableNetwork.copyOf(mutableNetwork); 253  } 254  } 255 }