/* * 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.Collection; import java.util.Collections; import java.util.Iterator; /** * Doubled digraph implementation. * * @param <V> vertex type * @param <E> edge type */ public class DoubledDigraphAdapter<V,E> extends DigraphAdapter<V,E> implements DoubledDigraph<V,E> { /** * Factory creating <code>DoubledDigraph</code>. * @param factory delegate factory * @return doubled digraph factory */ public static <V,E> DigraphFactory<DoubledDigraphAdapter<V,E>> getAdapterFactory(final DigraphFactory<? extends Digraph<V,E>> factory) { return new DigraphFactory<DoubledDigraphAdapter<V,E>>() { @Override public DoubledDigraphAdapter<V,E> create() { return new DoubledDigraphAdapter<V,E>(factory); } }; } private final DoubledDigraphAdapter<V,E> reverse; private final DigraphFactory<? extends Digraph<V,E>> factory; public DoubledDigraphAdapter() { this(MapDigraph.<V,E>getDefaultDigraphFactory()); } public DoubledDigraphAdapter(DigraphFactory<? extends Digraph<V,E>> factory) { super(factory.create()); this.factory = factory; this.reverse = createReverse(); } protected DoubledDigraphAdapter(DigraphFactory<? extends Digraph<V,E>> factory, DoubledDigraphAdapter<V,E> reverse) { super(factory.create()); this.factory = factory; this.reverse = reverse; } protected DoubledDigraphAdapter<V,E> createReverse() { return new DoubledDigraphAdapter<V, E>(factory, this); } protected DigraphFactory<? extends DoubledDigraph<V, E>> getDigraphFactory() { return getAdapterFactory(factory); } protected DigraphFactory<? extends Digraph<V,E>> getDelegateFactory() { return factory; } @Override public int getInDegree(Object vertex) { return reverse.getOutDegree(vertex); } @Override public Iterable<V> sources(Object target) { return reverse.targets(target); } @Override public final boolean add(V vertex) { reverse.add0(vertex); return add0(vertex); } protected boolean add0(V vertex) { return super.add(vertex); } @Override public final boolean remove(V vertex) { reverse.remove0(vertex); return remove0(vertex); } protected boolean remove0(V vertex) { return super.remove(vertex); } @Override public void removeAll(Collection<V> vertices) { reverse.removeAll0(vertices); removeAll0(vertices); } protected void removeAll0(Collection<V> vertices) { super.removeAll(vertices); } /** * Make sure the reverse digraph is kept in sync if <code>Iterator.remove()</code> is called. */ @Override public Iterable<V> vertices() { final Iterator<V> delegate = super.vertices().iterator(); if (!delegate.hasNext()) { return Collections.emptySet(); } return new Iterable<V>() { @Override public Iterator<V> iterator() { return new Iterator<V>() { V vertex; @Override public boolean hasNext() { return delegate.hasNext(); } @Override public V next() { return vertex = delegate.next(); } @Override public void remove() { delegate.remove(); reverse.remove0(vertex); } }; } @Override public String toString() { return DoubledDigraphAdapter.super.vertices().toString(); } }; } /** * Make sure the reverse digraph is kept in sync if <code>Iterator.remove()</code> is called. */ @Override public Iterable<V> targets(final Object source) { final Iterator<V> delegate = super.targets(source).iterator(); if (!delegate.hasNext()) { return Collections.emptySet(); } return new Iterable<V>() { @Override public Iterator<V> iterator() { return new Iterator<V>() { V target; @Override public boolean hasNext() { return delegate.hasNext(); } @Override public V next() { return target = delegate.next(); } @Override public void remove() { delegate.remove(); @SuppressWarnings("unchecked") V v = (V)source; reverse.remove0(target, v); } }; } @Override public String toString() { return DoubledDigraphAdapter.super.targets(source).toString(); } }; } @Override public final E put(V source, V target, E edge) { reverse.put0(target, source, edge); return put0(source, target, edge); } protected E put0(V source, V target, E edge) { return super.put(source, target, edge); } @Override public final E remove(V source, V target) { reverse.remove0(target, source); return remove0(source, target); } protected E remove0(V source, V target) { return super.remove(source, target); } @Override public final DoubledDigraphAdapter<V, E> reverse() { return reverse; } }