/* * 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; /** * Doubled digraph implementation. * * @param <V> vertex type * @param <E> edge type */ public class SimpleDigraphAdapter<V> extends DigraphAdapter<V, Boolean> implements SimpleDigraph<V> { /** * Factory creating <code>SimpleDigraph</code>. * @param factory delegate factory * @return simple digraph factory */ public static <V> DigraphFactory<SimpleDigraphAdapter<V>> getAdapterFactory(final DigraphFactory<? extends Digraph<V,Boolean>> factory) { return new DigraphFactory<SimpleDigraphAdapter<V>>() { @Override public SimpleDigraphAdapter<V> create() { return new SimpleDigraphAdapter<V>(factory); } }; } private static final EdgeCumulator<Object,Integer,Boolean> COUNT_CUMULATOR = new EdgeCumulator<Object,Integer,Boolean>() { @Override public Integer add(Object source, Object target, Integer edge, Boolean operand) { return Integer.valueOf(edge == null ? 1 : edge.intValue() + 1); } }; private final DigraphFactory<? extends Digraph<V,Boolean>> factory; public SimpleDigraphAdapter() { this(MapDigraph.<V,Boolean>getDefaultDigraphFactory()); } public SimpleDigraphAdapter(DigraphFactory<? extends Digraph<V,Boolean>> factory) { this(factory, factory.create()); } protected SimpleDigraphAdapter(DigraphFactory<? extends Digraph<V,Boolean>> factory, Digraph<V,Boolean> delegate) { super(delegate); this.factory = factory; } protected DigraphFactory<? extends SimpleDigraph<V>> getDigraphFactory() { return getAdapterFactory(factory); } protected DigraphFactory<? extends Digraph<V,Boolean>> getDelegateFactory() { return factory; } @Override public boolean add(V source, V target) { return super.put(source, target, Boolean.TRUE) == null ? Boolean.TRUE : Boolean.FALSE; } @Override public Boolean remove(V source, V target) { return super.remove(source, target) == null ? Boolean.FALSE : Boolean.TRUE; } @Override public Boolean put(V source, V target, Boolean edge) { if (!Boolean.TRUE.equals(edge)) { // or should we simply ignore the supplied edge value? throw new IllegalArgumentException("illegal: edge must be TRUE; use add(source, target) instead!"); } return add(source, target); } @Override public SimpleDigraph<V> reverse() { return new SimpleDigraphAdapter<V>(getDigraphFactory(), super.reverse()); } @Override public SimpleDigraph<V> subgraph(Set<V> vertices) { return new SimpleDigraphAdapter<V>(getDigraphFactory(), super.subgraph(vertices)); } /** * Compute the component graph. The component are <code>SimpleDigraph<V></code> created by * {@link #getDigraphFactory()}. * The outer graph is a {@link WeightedDigraph} whose edges are labelled with integers * giving the number of edges between components in the original (this) graph. */ public WeightedDigraph<SimpleDigraph<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 simple V digraph vertices and Integer edges DigraphFactory<? extends Digraph<SimpleDigraph<V>,Integer>> rawFactory = MapDigraph.getDefaultDigraphFactory(); // adapter factory to create a weighted digraph from the above DigraphFactory<? extends WeightedDigraph<SimpleDigraph<V>>> outerFactory = WeightedDigraphAdapter.getAdapterFactory(rawFactory); // answer partition graph return Digraphs.partition(this, components, outerFactory, getDigraphFactory(), COUNT_CUMULATOR); } }