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 com.google.common.annotations.Beta; 020import com.google.common.base.Function; 021import com.google.common.collect.Maps; 022import java.util.Map; 023import java.util.Optional; 024import java.util.Set; 025import org.checkerframework.checker.nullness.compatqual.NullableDecl; 026 027/** 028 * This class provides a skeletal implementation of {@link ValueGraph}. It is recommended to extend 029 * this class rather than implement {@link ValueGraph} directly. 030 * 031 * <p>The methods implemented in this class should not be overridden unless the subclass admits a 032 * more efficient implementation. 033 * 034 * @author James Sexton 035 * @param <N> Node parameter type 036 * @param <V> Value parameter type 037 * @since 20.0 038 */ 039@Beta 040public abstract class AbstractValueGraph<N, V> extends AbstractBaseGraph<N> 041 implements ValueGraph<N, V> { 042 043 @Override 044 public Graph<N> asGraph() { 045 return new AbstractGraph<N>() { 046 @Override 047 public Set<N> nodes() { 048 return AbstractValueGraph.this.nodes(); 049 } 050 051 @Override 052 public Set<EndpointPair<N>> edges() { 053 return AbstractValueGraph.this.edges(); 054 } 055 056 @Override 057 public boolean isDirected() { 058 return AbstractValueGraph.this.isDirected(); 059 } 060 061 @Override 062 public boolean allowsSelfLoops() { 063 return AbstractValueGraph.this.allowsSelfLoops(); 064 } 065 066 @Override 067 public ElementOrder<N> nodeOrder() { 068 return AbstractValueGraph.this.nodeOrder(); 069 } 070 071 @Override 072 public Set<N> adjacentNodes(N node) { 073 return AbstractValueGraph.this.adjacentNodes(node); 074 } 075 076 @Override 077 public Set<N> predecessors(N node) { 078 return AbstractValueGraph.this.predecessors(node); 079 } 080 081 @Override 082 public Set<N> successors(N node) { 083 return AbstractValueGraph.this.successors(node); 084 } 085 086 @Override 087 public int degree(N node) { 088 return AbstractValueGraph.this.degree(node); 089 } 090 091 @Override 092 public int inDegree(N node) { 093 return AbstractValueGraph.this.inDegree(node); 094 } 095 096 @Override 097 public int outDegree(N node) { 098 return AbstractValueGraph.this.outDegree(node); 099 } 100 }; 101 } 102 103 @Override 104 public Optional<V> edgeValue(N nodeU, N nodeV) { 105 return Optional.ofNullable(edgeValueOrDefault(nodeU, nodeV, null)); 106 } 107 108 @Override 109 public final boolean equals(@NullableDecl Object obj) { 110 if (obj == this) { 111 return true; 112 } 113 if (!(obj instanceof ValueGraph)) { 114 return false; 115 } 116 ValueGraph<?, ?> other = (ValueGraph<?, ?>) obj; 117 118 return isDirected() == other.isDirected() 119 && nodes().equals(other.nodes()) 120 && edgeValueMap(this).equals(edgeValueMap(other)); 121 } 122 123 @Override 124 public final int hashCode() { 125 return edgeValueMap(this).hashCode(); 126 } 127 128 /** Returns a string representation of this graph. */ 129 @Override 130 public String toString() { 131 return "isDirected: " 132 + isDirected() 133 + ", allowsSelfLoops: " 134 + allowsSelfLoops() 135 + ", nodes: " 136 + nodes() 137 + ", edges: " 138 + edgeValueMap(this); 139 } 140 141 private static <N, V> Map<EndpointPair<N>, V> edgeValueMap(final ValueGraph<N, V> graph) { 142 Function<EndpointPair<N>, V> edgeToValueFn = 143 new Function<EndpointPair<N>, V>() { 144 @Override 145 public V apply(EndpointPair<N> edge) { 146 return graph.edgeValueOrDefault(edge.nodeU(), edge.nodeV(), null); 147 } 148 }; 149 return Maps.asMap(graph.edges(), edgeToValueFn); 150 } 151}