/* * EuroCarbDB, a framework for carbohydrate bioinformatics * * Copyright (c) 2006-2009, Eurocarb project, or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * A copy of this license accompanies this distribution in the file LICENSE.txt. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * Last commit: $Rev: 1423 $ by $Author: glycoslave $ on $Date:: 2009-07-05 #$ */ package org.eurocarbdb.util.graph; import java.util.Set; import java.util.List; import java.util.HashSet; import java.util.ArrayList; import java.util.Collections; import java.io.Serializable; import org.eurocarbdb.util.graph.Edge; /* class Vertex *//************************************************ * * Wrapper class for <em>vertices</em> in a {@link Graph}. * Like edges, this class is <em>parameterised</em> by {@link Edge} * (E) and Vertex (V) type. * * @see Graph * @see Edge * @version $Rev: 1423 $ * @author mjh */ public class Vertex<E,V> implements Serializable, Comparable<Vertex<E,V>> { //~~~~~~~~~~~~~~~~~~~~~~~~ FIELDS ~~~~~~~~~~~~~~~~~~~~~~~~~~~// /** Value of this vertex. */ final V value; /** */ int index = -1; /** List of attached edges, lazily initialised. */ // private List<Edge<E,V>> attachedEdges = Collections.emptyList(); private Set<Edge<E,V>> attachedEdges = Collections.emptySet(); // /** Whether this vertex is at the periphery of the graph. // * ATM this is read & modified directly from with the Graph class. */ // private boolean isLeaf = true; //~~~~~~~~~~~~~~~~~~~~~~ CONSTRUCTORS ~~~~~~~~~~~~~~~~~~~~~~~// /** Sole constructor. */ protected Vertex( V value ) { this.value = value; } //~~~~~~~~~~~~~~~~~~~~~~~~ METHODS ~~~~~~~~~~~~~~~~~~~~~~~~~~// public int compareTo( Vertex<E,V> other ) { return ((Integer) this.index).compareTo( other.index ); } public boolean equals( Vertex<E,V> other ) { return this.index == other.index; } /** Connects this vertex to another vertex with the given Edge. */ protected void addEdge( Edge<E,V> edge ) { _lazy_init(); attachedEdges.add( edge ); } /** Returns the number of edges attached to this Vertex. */ public int countAttachedEdges() { return attachedEdges.size(); } /** Returns the number of vertices attached to this Vertex. */ public int countAttachedVertices() { //return getAttachedVertices().size(); int vertices = 0; for ( Edge<E,V> e : attachedEdges ) if ( e.getParent() != e.getChild() ) vertices++; return vertices; } /** * Pre-allocates memory for the specified number of Edges that will * be attached to this vertex. The purpose of this method is to * prevent multiple re-hashes if the number of Edges to add is large, * of if the final number of Edges for this vertex is known in advance. */ public void ensureCapacity( int size ) { if ( size <= attachedEdges.size() ) return; Graph.log.debug("setting expected capacity of vertex=" + this + " to " + size ); if ( attachedEdges == Collections.EMPTY_SET ) { // loadFactor == 1.0 cause we expect the user knows the // exact number of Edges they are expecting to add, and // loadFactor == 1.0 means no rehashing as long as user // adds <= size elements. attachedEdges = new HashSet<Edge<E,V>>( size, 1.0f ); return; } // if size is more than a trivial number and is decently // larger than current size, then re-create as a larger Set, // otherwise, let Set dynamically resize itself as per usual. if ( size > attachedEdges.size() * 4 && size > 64 ) { Set<Edge<E,V>> resized = new HashSet<Edge<E,V>>( size ); resized.addAll( attachedEdges ); attachedEdges = resized; return; } } /** Returns the value of this vertex. */ public V getValue() { return this.value; } /** Returns the list of the values of the edges associated with this Vertex. */ public List<E> getAttachedEdgeValues() { List<E> values = new ArrayList<E>( attachedEdges.size() ); for ( Edge<E,V> v : attachedEdges ) values.add( v.getValue() ); return values; } /** Returns the (unmodifiable) list of Edges attached to this Vertex. */ public Set<Edge<E,V>> getAttachedEdges() { return Collections.unmodifiableSet( attachedEdges ); } /** * Returns the Set of Vertices attached to this Vertex. External modification of * this set does not affect the Graph. */ public Set<Vertex<E,V>> getAttachedVertices() { Set<Vertex<E,V>> attachedVertices = new HashSet<Vertex<E,V>>( attachedEdges.size() ); for ( Edge<E,V> e : attachedEdges ) { Vertex<E,V> v = e.getVertexOpposite( this ); if ( v == this ) continue; attachedVertices.add( v ); } return attachedVertices; } /** Returns the list of the values of the vertices attached to this Vertex. */ public Set<V> getAttachedVertexValues() { Set<Vertex<E,V>> attachedVertices = getAttachedVertices(); Set<V> values = new HashSet<V>( attachedVertices.size() ); for ( Vertex<E,V> v : attachedVertices ) values.add( v.getValue() ); return values; } /** * Returns only {@link Edge}s for which this vertex is the child * vertex of that edge. */ public List<Edge<E,V>> getIncomingEdges() { List<Edge<E,V>> incoming = new ArrayList<Edge<E,V>>(); for ( Edge<E,V> e : attachedEdges ) { if ( e.child == this ) incoming.add( e ); } return incoming; } /** * Returns only {@link Edge}s for which this vertex is the parent * vertex of that edge. */ public List<Edge<E,V>> getOutgoingEdges() { List<Edge<E,V>> incoming = new ArrayList<Edge<E,V>>(); for ( Edge<E,V> e : attachedEdges ) { if ( e.parent == this ) incoming.add( e ); } return incoming; } /** Returns whether this vertex has attached vertices. */ public boolean hasAttachedVertices() { for ( Edge<E,V> e : attachedEdges ) if ( e.getParent() != this || e.getChild() != this ) return true; return false; } /** * This method is overriden to return the hashcode of the *value* of * this vertex, not the vertex itself. What this means is that vertex * values must be *unique* per graph. * * @see java.lang.Object#hashCode() */ public int hashCode() { return value.hashCode(); } /** Removes the given edge from this vertex. */ protected boolean removeEdge( Edge edge ) { return attachedEdges.remove( edge ); } /** Returns this Vertex's value as a string. */ public String toString() { return "Vertex=" + value.toString(); } /** Lazily initialises internal lists for attahed vertices & edges. */ private final void _lazy_init() { if ( attachedEdges == Collections.EMPTY_SET ) attachedEdges = new HashSet<Edge<E,V>>( Graph.Default_Number_Of_Children ); } } // end class Vertex -------------------------------------------