001/* 002 * Copyright (C) 2016 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.google.common.graph; 018 019import static java.util.Objects.requireNonNull; 020 021import com.google.common.annotations.Beta; 022import com.google.common.collect.Maps; 023import java.util.Map; 024import java.util.Optional; 025import java.util.Set; 026import javax.annotation.CheckForNull; 027 028/** 029 * This class provides a skeletal implementation of {@link ValueGraph}. It is recommended to extend 030 * this class rather than implement {@link ValueGraph} directly. 031 * 032 * <p>The methods implemented in this class should not be overridden unless the subclass admits a 033 * more efficient implementation. 034 * 035 * @author James Sexton 036 * @param <N> Node parameter type 037 * @param <V> Value parameter type 038 * @since 20.0 039 */ 040@Beta 041@ElementTypesAreNonnullByDefault 042public abstract class AbstractValueGraph<N, V> extends AbstractBaseGraph<N> 043 implements ValueGraph<N, V> { 044 /** Constructor for use by subclasses. */ 045 public AbstractValueGraph() {} 046 047 @Override 048 public Graph<N> asGraph() { 049 return new AbstractGraph<N>() { 050 @Override 051 public Set<N> nodes() { 052 return AbstractValueGraph.this.nodes(); 053 } 054 055 @Override 056 public Set<EndpointPair<N>> edges() { 057 return AbstractValueGraph.this.edges(); 058 } 059 060 @Override 061 public boolean isDirected() { 062 return AbstractValueGraph.this.isDirected(); 063 } 064 065 @Override 066 public boolean allowsSelfLoops() { 067 return AbstractValueGraph.this.allowsSelfLoops(); 068 } 069 070 @Override 071 public ElementOrder<N> nodeOrder() { 072 return AbstractValueGraph.this.nodeOrder(); 073 } 074 075 @Override 076 public ElementOrder<N> incidentEdgeOrder() { 077 return AbstractValueGraph.this.incidentEdgeOrder(); 078 } 079 080 @Override 081 public Set<N> adjacentNodes(N node) { 082 return AbstractValueGraph.this.adjacentNodes(node); 083 } 084 085 @Override 086 public Set<N> predecessors(N node) { 087 return AbstractValueGraph.this.predecessors(node); 088 } 089 090 @Override 091 public Set<N> successors(N node) { 092 return AbstractValueGraph.this.successors(node); 093 } 094 095 @Override 096 public int degree(N node) { 097 return AbstractValueGraph.this.degree(node); 098 } 099 100 @Override 101 public int inDegree(N node) { 102 return AbstractValueGraph.this.inDegree(node); 103 } 104 105 @Override 106 public int outDegree(N node) { 107 return AbstractValueGraph.this.outDegree(node); 108 } 109 }; 110 } 111 112 @Override 113 public Optional<V> edgeValue(N nodeU, N nodeV) { 114 return Optional.ofNullable(edgeValueOrDefault(nodeU, nodeV, null)); 115 } 116 117 @Override 118 public Optional<V> edgeValue(EndpointPair<N> endpoints) { 119 return Optional.ofNullable(edgeValueOrDefault(endpoints, null)); 120 } 121 122 @Override 123 public final boolean equals(@CheckForNull Object obj) { 124 if (obj == this) { 125 return true; 126 } 127 if (!(obj instanceof ValueGraph)) { 128 return false; 129 } 130 ValueGraph<?, ?> other = (ValueGraph<?, ?>) obj; 131 132 return isDirected() == other.isDirected() 133 && nodes().equals(other.nodes()) 134 && edgeValueMap(this).equals(edgeValueMap(other)); 135 } 136 137 @Override 138 public final int hashCode() { 139 return edgeValueMap(this).hashCode(); 140 } 141 142 /** Returns a string representation of this graph. */ 143 @Override 144 public String toString() { 145 return "isDirected: " 146 + isDirected() 147 + ", allowsSelfLoops: " 148 + allowsSelfLoops() 149 + ", nodes: " 150 + nodes() 151 + ", edges: " 152 + edgeValueMap(this); 153 } 154 155 private static <N, V> Map<EndpointPair<N>, V> edgeValueMap(final ValueGraph<N, V> graph) { 156 return Maps.asMap( 157 graph.edges(), 158 edge -> 159 // requireNonNull is safe because the endpoint pair comes from the graph. 160 requireNonNull(graph.edgeValueOrDefault(edge.nodeU(), edge.nodeV(), null))); 161 } 162}