/* * Copyright 2012 Odysseus Software GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.odysseus.ithaka.digraph; import java.util.List; import java.util.Set; public class WeightedDigraphAdapter<V> extends DigraphAdapter<V, Integer> implements WeightedDigraph<V> { public static <V> DigraphFactory<WeightedDigraphAdapter<V>> getAdapterFactory(final DigraphFactory<? extends Digraph<V,Integer>> factory) { return new DigraphFactory<WeightedDigraphAdapter<V>>() { @Override public WeightedDigraphAdapter<V> create() { return new WeightedDigraphAdapter<V>(factory); } }; } private static final EdgeCumulator<Object,Integer,Integer> ADD_CUMULATOR = new EdgeCumulator<Object,Integer,Integer>() { @Override public Integer add(Object source, Object target, Integer edge, Integer operand) { return edge == null ? operand : Integer.valueOf(edge.intValue() + operand.intValue()); } }; private final DigraphFactory<? extends Digraph<V,Integer>> factory; public WeightedDigraphAdapter() { this(MapDigraph.<V,Integer>getDefaultDigraphFactory()); } public WeightedDigraphAdapter(DigraphFactory<? extends Digraph<V,Integer>> factory) { this(factory, factory.create()); } protected WeightedDigraphAdapter(DigraphFactory<? extends Digraph<V,Integer>> factory, Digraph<V,Integer> delegate) { super(delegate); this.factory = factory; } @Override public void add(V source, V target, int weight) { Integer current = get(source, target); put(source, target, current == null ? weight : current.intValue() + weight); } protected DigraphFactory<? extends WeightedDigraph<V>> getDigraphFactory() { return getAdapterFactory(factory); } protected DigraphFactory<? extends Digraph<V,Integer>> getDelegateFactory() { return factory; } @Override public WeightedDigraph<V> reverse() { return new WeightedDigraphAdapter<V>(getDigraphFactory(), super.reverse()); } @Override public WeightedDigraph<V> subgraph(Set<V> vertices) { return new WeightedDigraphAdapter<V>(getDigraphFactory(), super.subgraph(vertices)); } @Override public int totalWeight() { int weight = 0; for (V source : vertices()) { for (V target : targets(source)) { weight += get(source, target); } } return weight; } /** * Compute the component graph. The component are <code>WeightedDigraph<V></code>s. * The outer graph is a {@link WeightedDigraph} whose edges are labelled with integers * giving the sum of edge weights between components in the original (this) graph. */ public WeightedDigraph<WeightedDigraph<V>> partition(boolean weak) { // compute component sets List<Set<V>> components = weak ? Digraphs.<V>wcc(this) : Digraphs.<V>scc(this); // factory to create a digraph with weighted V digraph vertices and Integer edges DigraphFactory<? extends Digraph<WeightedDigraph<V>,Integer>> rawFactory = MapDigraph.getDefaultDigraphFactory(); // adapter factory to create a weighted digraph from the above DigraphFactory<? extends WeightedDigraph<WeightedDigraph<V>>> outerFactory = WeightedDigraphAdapter.getAdapterFactory(rawFactory); // answer partition graph return Digraphs.partition(this, components, outerFactory, getDigraphFactory(), ADD_CUMULATOR); } }