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.qual.Nullable; 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 ElementOrder<N> incidentEdgeOrder() { 073 return AbstractValueGraph.this.incidentEdgeOrder(); 074 } 075 076 @Override 077 public Set<N> adjacentNodes(N node) { 078 return AbstractValueGraph.this.adjacentNodes(node); 079 } 080 081 @Override 082 public Set<N> predecessors(N node) { 083 return AbstractValueGraph.this.predecessors(node); 084 } 085 086 @Override 087 public Set<N> successors(N node) { 088 return AbstractValueGraph.this.successors(node); 089 } 090 091 @Override 092 public int degree(N node) { 093 return AbstractValueGraph.this.degree(node); 094 } 095 096 @Override 097 public int inDegree(N node) { 098 return AbstractValueGraph.this.inDegree(node); 099 } 100 101 @Override 102 public int outDegree(N node) { 103 return AbstractValueGraph.this.outDegree(node); 104 } 105 }; 106 } 107 108 @Override 109 public Optional<V> edgeValue(N nodeU, N nodeV) { 110 return Optional.ofNullable(edgeValueOrDefault(nodeU, nodeV, null)); 111 } 112 113 @Override 114 public Optional<V> edgeValue(EndpointPair<N> endpoints) { 115 return Optional.ofNullable(edgeValueOrDefault(endpoints, null)); 116 } 117 118 @Override 119 public final boolean equals(@Nullable Object obj) { 120 if (obj == this) { 121 return true; 122 } 123 if (!(obj instanceof ValueGraph)) { 124 return false; 125 } 126 ValueGraph<?, ?> other = (ValueGraph<?, ?>) obj; 127 128 return isDirected() == other.isDirected() 129 && nodes().equals(other.nodes()) 130 && edgeValueMap(this).equals(edgeValueMap(other)); 131 } 132 133 @Override 134 public final int hashCode() { 135 return edgeValueMap(this).hashCode(); 136 } 137 138 /** Returns a string representation of this graph. */ 139 @Override 140 public String toString() { 141 return "isDirected: " 142 + isDirected() 143 + ", allowsSelfLoops: " 144 + allowsSelfLoops() 145 + ", nodes: " 146 + nodes() 147 + ", edges: " 148 + edgeValueMap(this); 149 } 150 151 private static <N, V> Map<EndpointPair<N>, V> edgeValueMap(final ValueGraph<N, V> graph) { 152 Function<EndpointPair<N>, V> edgeToValueFn = 153 new Function<EndpointPair<N>, V>() { 154 @Override 155 public V apply(EndpointPair<N> edge) { 156 return graph.edgeValueOrDefault(edge.nodeU(), edge.nodeV(), null); 157 } 158 }; 159 return Maps.asMap(graph.edges(), edgeToValueFn); 160 } 161}